package org.soulraven.games.memory.ui.game;

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

import org.soulraven.games.memory.engine.MemoryEngine;
import org.soulraven.games.memory.model.Game;
import org.soulraven.games.memory.model.Player;
import org.soulraven.games.memory.ui.game.controller.GameController;
import org.soulraven.games.memory.util.ImageUtil;
import org.soulraven.games.memory.util.MessageUtil;

public class GameFrame extends JFrame {

	private static final long serialVersionUID = -8262076902236362150L;

	private MainPanel mainPanel = null;
	private JLabel statusBar = null;
	private MemoryEngine engine = null;
	private Game game = null;
	private JMenu fileMenu = null;
	private JMenu helpMenu = null;
	private JMenuItem exitMenuItem = null;
	private JMenuItem aboutMenuItem = null;
	private GameController controller = null;

	public GameFrame(final MemoryEngine engine, final Game game) {
		this.engine = engine;
		this.game = game;
		this.controller = new GameController(this);
		initialize();
		initializePlayers();
	}

	private void initialize() {
		this.setIconImage(ImageUtil.getFavicon().getImage());
		this.setTitle(MessageUtil.getMessage("gametitle"));
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		this.addWindowListener(controller);
		this.setLayout(new BorderLayout(5, 5));
		this.add(getMainPanel(), BorderLayout.CENTER);
		this.add(getStatusBar(), BorderLayout.SOUTH);
		JMenuBar jMenuBar = new JMenuBar();
		jMenuBar.add(getFileMenu());
		jMenuBar.add(getHelpMenu());
		this.setJMenuBar(jMenuBar);
		this.setLocationRelativeTo(null);
		this.pack();
	}

	private void initializePlayers() {
		Player currentPlayer = engine.getCurrentPlayer();
		updateStatusBar(currentPlayer);
	}

	/**
	 * @return the mainPanel
	 */
	private MainPanel getMainPanel() {
		if (mainPanel == null) {
			this.mainPanel = new MainPanel(CardsGridBuilder.build(game
					.getDifficulty(), engine.getSelectionController()));
		}
		return mainPanel;
	}

	/**
	 * @return the statusBar
	 */
	private JLabel getStatusBar() {
		if (statusBar == null) {
			statusBar = new JLabel("");
		}
		return statusBar;
	}

	/**
	 * @return the menu
	 */
	private JMenu getFileMenu() {
		if (fileMenu == null) {
			fileMenu = new JMenu(MessageUtil.getMessage("filemenu"));
			fileMenu.add(getExitMenuItem());
		}
		return fileMenu;
	}

	/**
	 * @return the helpMenu
	 */
	private JMenu getHelpMenu() {
		if (helpMenu == null) {
			helpMenu = new JMenu(MessageUtil.getMessage("helpmenu"));
			helpMenu.add(getAboutMenuItem());
		}
		return helpMenu;
	}

	/**
	 * @return the exitMenuItem
	 */
	private JMenuItem getExitMenuItem() {
		if (exitMenuItem == null) {
			exitMenuItem = new JMenuItem(MessageUtil.getMessage("exitmenuitem"));
			exitMenuItem.addActionListener(controller);
		}
		return exitMenuItem;
	}

	/**
	 * @return the aboutMenuItem
	 */
	private JMenuItem getAboutMenuItem() {
		if (aboutMenuItem == null) {
			aboutMenuItem = new JMenuItem(MessageUtil.getMessage("aboutmenuitem"));
		}
		return aboutMenuItem;
	}

	public void updateStatusBar(final Player player) {
		final String status = MessageUtil.getMessage("playerturn",
				new Object[] { player.getName() });
		getStatusBar().setText(status);
	}

	public void pairShown(final boolean match) {
		final String status = MessageUtil.getMessage(match ? "match"
				: "nomatch");
		getStatusBar().setText(status);
	}

	public void disableAllCards() {
		mainPanel.disableAllCards();
	}

	public void enableAllSelectableCards() {
		mainPanel.enableAllSelectableCards();
	}

	public boolean isEndGame() {
		return mainPanel.areAllCardsDisabled();
	}

	public void setWinner(final Player player) {
		final String status = MessageUtil.getMessage("winner",
				new Object[] { player.getName() });
		getStatusBar().setText(status);
	}

	public void setTie() {
		final String status = MessageUtil.getMessage("tie");
		getStatusBar().setText(status);
	}

	public void setScore(final Player player) {
		final String status = MessageUtil.getMessage("endgamescore",
				new Object[] { player.getScore() });
		getStatusBar().setText(status);
	}
}
